/*
 * © Copyright 2011 Romain Marteau, Matthieu Totet
 * 
 *    This file is part of VineaToum.
 *
 *    VineaToum is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    VineaToum is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with VineaToum.  If not, see <http://www.gnu.org/licenses/>.
 *    
 */

package org.vineatoum.business;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlID;
import javax.xml.bind.annotation.XmlIDREF;
import javax.xml.bind.annotation.XmlRootElement;

import org.vineatoum.business.configuration.Appellation;
import org.vineatoum.business.configuration.Cepage;
import org.vineatoum.business.state.Raisin;
import org.vineatoum.business.state.abstraction.VinAbstract;
import org.vineatoum.view.utils.jtablecustom.TableListener;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "plantation")
public class Plantation extends VinAbstract {
	public static List<Plantation> plantations = new ArrayList<Plantation>();
	@XmlID
	@XmlElement
	private String name;
	@XmlIDREF
	@XmlElement
	private Cepage cepage;
	@XmlIDREF
	@XmlElement
	private Appellation appellation;
	@XmlElement
	private float surfaceArea;
	@XmlElement
	private float cepGap;
	@XmlElement
	private float rowGap;
	@XmlElement
	private int cepDensity;
	@XmlElement
	private int plantationYear;
	private Map<Integer, Raisin> vintages;
	@XmlIDREF
	@XmlElement(name = "parcelle")
	@XmlElementWrapper(name = "parcelles")
	private List<Parcelle> parcelles;

	public Plantation() {
		plantations.add(this);
		parcelles = new ArrayList<Parcelle>();
		plantationYear = 2000;
		surfaceArea = 1;
		cepGap = new Float(1.5);
		rowGap = new Float(1.5);
		cepDensity = 4500;
	}

	public Plantation(String name) {
		this.name = name;
		vintages = new HashMap<Integer, Raisin>();
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name
	 *            the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return the cepage
	 */
	public Cepage getCepage() {
		return cepage;
	}

	/**
	 * @param cepage
	 *            the cepage to set
	 */
	public void setCepage(Cepage cepage) {
		this.cepage = cepage;
	}

	/**
	 * @return the appellation
	 */
	public Appellation getAppellation() {
		return appellation;
	}

	/**
	 * @param appellation
	 *            the appellation to set
	 */
	public void setAppellation(Appellation appellation) {
		this.appellation = appellation;
	}

	/**
	 * @return the surfaceArea
	 */
	public float getSurfaceArea() {
		return surfaceArea;
	}

	/**
	 * @param surfaceArea
	 *            the surfaceArea to set
	 */
	public void setSurfaceArea(float surfaceArea) {
		this.surfaceArea = surfaceArea;
	}

	/**
	 * @return the cepGap
	 */
	public float getCepGap() {
		return cepGap;
	}

	/**
	 * @param cepGap
	 *            the cepGap to set
	 */
	public void setCepGap(float cepGap) {
		this.cepGap = cepGap;
	}

	/**
	 * @return the rowGap
	 */
	public float getRowGap() {
		return rowGap;
	}

	/**
	 * @param rowGap
	 *            the rowGap to set
	 */
	public void setRowGap(float rowGap) {
		this.rowGap = rowGap;
	}

	/**
	 * @return the cepDensity
	 */
	public int getCepDensity() {
		return cepDensity;
	}

	/**
	 * @param cepDensity
	 *            the cepDensity to set
	 */
	public void setCepDensity(int cepDensity) {
		this.cepDensity = cepDensity;
	}

	/**
	 * @param plantationYear the plantationYear to set
	 */
	public void setPlantationYear(int plantationYear) {
		this.plantationYear = plantationYear;
	}

	/**
	 * @return the plantationYear
	 */
	public int getPlantationYear() {
		return plantationYear;
	}

	public Raisin getVintage(int vintage) {
		if (vintages.containsKey(vintage)) {
			return vintages.get(vintage);
		} else {
			Raisin raisin = new Raisin();
			raisin.setVintage(vintage);
			vintages.put(vintage, raisin);
			return raisin;
		}
	}

	/**
	 * @param vintages
	 *            the vintages to set
	 */
	public void addVintage(int vintage) {
		if (!vintages.containsKey(vintage)) {
			this.vintages.put(vintage, new Raisin());
		} else {
			throw new RuntimeException("Vintage " + vintage
					+ " already exists for the plantation " + name);
		}
	}

	public List<Parcelle> getParcelles() {
		return parcelles;
	}

	/**
	 * @param parcelle
	 */
	public void addParcelle(Parcelle parcelle) {
		parcelles.add(parcelle);
	}

	@Override
	public TableListener getNewInstance() {
		return new Plantation();
	}

	@Override
	public Vector<Object> getVectorData() {
		DecimalFormat df = new DecimalFormat("########.##"); 
		
		Vector<Object> vector = new Vector<Object>();
		vector.add(name);
		vector.add(cepage);
		vector.add(appellation);
		vector.add(df.format(surfaceArea));
		vector.add(plantationYear);		
		vector.add(df.format(cepGap));
		vector.add(df.format(rowGap));
		vector.add(cepDensity);
		vector.add(parcelles);
		return vector;
	}

	@Override
	public void updateField(String field, Object value) {
		try {
			if (field.equals("Nom")) {
				this.name = (String) value;
			} else if (field.equals("Cépage")) {
				this.cepage = (Cepage) value;
			} else if (field.equals("Appellation")) {
				this.appellation = (Appellation) value;
			} else if (field.equals("Superficie")) {
				this.surfaceArea = (Float) value;
			} else if (field.equals("Ecartement des ceps")) {
				this.cepGap = (Float) value;
			} else if (field.equals("Année de plantation")) {
				this.plantationYear = (Integer) value;
			} else if (field.equals("Ecartement des rangs")) {
				this.rowGap = (Float) value;
			} else if (field.equals("Densité de ceps")) {
				this.cepDensity = (Integer) value;
			} else if (field.equals("Parcelles")) {
				Object[] p = (Object[])value;
				parcelles.clear();
				for (int i = 0; i < p.length; i++) {
					parcelles.add((Parcelle) p[i]);
				}
			}
		} catch (ClassCastException e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}

	@Override
	public String toString() {
		return name;
	}

	@Override
	public Vector<String> getVectorColumns() {
		Vector<String> vector = new Vector<String>();
		vector.add("Nom");
		vector.add("Cépage");
		vector.add("Appellation");
		vector.add("Superficie");
		vector.add("Année de plantation");
		vector.add("Ecartement des ceps");
		vector.add("Ecartement des rangs");
		vector.add("Densité de ceps");
		vector.add("Parcelles");
		return vector;
	}
}
